/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Data.Objects.DataClasses;
using System.Linq;
using Oceanside.Payments.Credit;
using Oceanside.Payments;

#if _LOCALDB
  using Oceanside.LocalDB;
#else
  using Oceanside.RemoteDB;
#endif

namespace Oceanside
{
    static class CCBindings
    {
        private static int _seatPivotIndex = 0;
        private static int _selectedSeatIndex = 0;

        public static int SelectedSeatIndex
        {
            get { return CCBindings._selectedSeatIndex; }
            set { CCBindings._selectedSeatIndex = value; }
        }
        private static int _custTicketScrollIndex = -1;
        private static int _selectedTransactionIndex = 0;
        public static int SelectedTransactionIndex
        {
            get { return CCBindings._selectedTransactionIndex; }
            set { CCBindings._selectedTransactionIndex = value; }
        }

        private static int _selectedDiscountIndex = 0;
        public static int SelectedDiscountIndex
        {
            get { return CCBindings._selectedDiscountIndex; }
            set { CCBindings._selectedDiscountIndex = value; }
        }

        private static SALE _selectedSale = null;
        public static SALE SelectedSale
        {
            get { return _selectedSale; }
            set { _selectedSale = value; }
        }

        public static TRANSACTION SelectedTransaction
        {
            get
            {
                return CloseCheckWindow.PaymentsGrid.DataContext as TRANSACTION;
            }
        }

        private static PRODUCT _selectedProduct = null;

        private static List<FlatButton_52_58> _seatButtonsList = new List<FlatButton_52_58>(4);

        public static void Init()
        {
            _seatButtonsList.Add(CloseCheckWindow.CheckPosition1);
            _seatButtonsList.Add(CloseCheckWindow.CheckPosition2);
            _seatButtonsList.Add(CloseCheckWindow.CheckPosition3);
            _seatButtonsList.Add(CloseCheckWindow.CheckPosition4);

            ///Wire in the event handlers for the check position buttons to be directly clicked.
            CloseCheckWindow.CheckPosition1.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            CloseCheckWindow.CheckPosition2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            CloseCheckWindow.CheckPosition3.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            CloseCheckWindow.CheckPosition4.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);

            CloseCheckWindow.ScrollDiscountLeft.OnFlatButtonClicked += new RoutedEventHandler(ScrollDiscountLeft_OnFlatButtonClicked);
            CloseCheckWindow.ScrollDiscountRight.OnFlatButtonClicked += new RoutedEventHandler(ScrollDiscountRight_OnFlatButtonClicked);

            ///Make sure to update the ticket index when it is clicked.
            CloseCheckWindow.CustomerTicketListView.SelectionChanged +=
                new SelectionChangedEventHandler(listViewCustTicket_SelectionChanged_NOTHROW);

            CloseCheckWindow.ScrollCheckLeft.OnFlatButtonClicked
                += new RoutedEventHandler(buttonScrollSeatLeft_Click_NOTHROW);
            CloseCheckWindow.ScrollCheckRight.OnFlatButtonClicked
                += new RoutedEventHandler(buttonScrollSeatRight_Click_NOTHROW);

            CloseCheckWindow.RemoveDiscountButton.MouseDown
                += new System.Windows.Input.MouseButtonEventHandler(RemoveDiscountButton_MouseDown);

            if (PaymentEngine.HasGift)
            {
                CloseCheckWindow.PrepaidBalanceButton.Visibility = Visibility.Visible;
                CloseCheckWindow.PrepaidBalanceButton.MouseDown +=
                    new System.Windows.Input.MouseButtonEventHandler(PrepaidBalanceButton_MouseDown);
            }
            else
            {
                CloseCheckWindow.PrepaidBalanceButton.Visibility = Visibility.Hidden;
            }

        }

        static AskForCCMessageBox _prepaidMessageBox = null;
        public static AskForCCMessageBox PrepaidMessageBox
        {
            get { return CCBindings._prepaidMessageBox; }
            set { CCBindings._prepaidMessageBox = value; }
        }

        static void PrepaidBalanceButton_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Constants.IsTrainingMode)
            {
                UMD.ShowGuiMessageSTASafe_NOTHROW("To protect cardholder data and remain PCI Compliant, credit card and gift card processing are not enabled while in training mode.");
            }
            else
            {
                _prepaidMessageBox = new AskForCCMessageBox("Please swipe the gift card or press the [X] to cancel.");
                _prepaidMessageBox.ShowDialog();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void RemoveDiscountButton_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            try
            {
                if (SHIFT.SelectedOrder.BusinessDayId == BUSINESS_DAY.GetNow(SHIFT.GlobalContext).Id)
                {
                    List<ORDER.DiscountDisplay> discounts = SHIFT.SelectedOrder.GetChecksDiscounts(SHIFT.SelectedOrder,
                        _selectedSeatIndex, SHIFT.GlobalContext);
                    ORDER.DiscountDisplay currDiscount = discounts[_selectedDiscountIndex];
                    if (currDiscount.IsItemLevelDiscount)
                    {
                        SALE s = SHIFT.SelectedOrder.SALES.Where(sa => sa.Id == currDiscount.AppliedToSaleId).FirstOrDefault();
                        if (s != null)
                        {
                            s.DiscountId = null;
                            s.DiscountManagerId = null;
                            s.DiscountRate = 0;
                            s.WasCompedInEntire = false;
                            s.WasVoided = false;

                            foreach (SALE modSale in s.MODSALES)
                            {
                                modSale.DiscountId = null;
                                modSale.DiscountManagerId = null;
                                modSale.DiscountRate = 0;
                                modSale.WasCompedInEntire = false;
                                modSale.WasVoided = false;
                            }
                        }
                    }
                    else
                    {
                        List<SALE> checksSales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
                        List<SALE> salesMatchingDisount =
                            checksSales.Where(s => s.DiscountAppliedAtCheckLevel && s.DiscountId == currDiscount.DiscountId).ToList();

                        foreach (SALE s in salesMatchingDisount)
                        {
                            s.DiscountId = null;
                            s.DiscountManagerId = null;
                            s.DiscountRate = 0;
                            s.DiscountAppliedAtCheckLevel = false;
                        }
                    }
                    SHIFT.GlobalContext.SaveChanges();
                    CCBindings.UpdateTicketFocus();
                    CCBindings.RefreshThreadSafe();
                    RefreshDiscountWindow(true);
                }
                else
                {
                    UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot delete a discount that occurred on a separate business day than today.");
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
        }

        static void ScrollDiscountRight_OnFlatButtonClicked(object sender, RoutedEventArgs e)
        {
            List<ORDER.DiscountDisplay> discounts = SHIFT.SelectedOrder.GetChecksDiscounts(SHIFT.SelectedOrder,
                    _selectedSeatIndex, SHIFT.GlobalContext);
            if (_selectedDiscountIndex < (discounts.Count() - 1))
            {
                _selectedDiscountIndex++;
            }
            else ///Wrap back to zero if we go over.
            {
                _selectedDiscountIndex = 0;
            }
            SetCurrentDiscountAtDiscountWindow(discounts);
        }

        static void ScrollDiscountLeft_OnFlatButtonClicked(object sender, RoutedEventArgs e)
        {
            List<ORDER.DiscountDisplay> discounts = SHIFT.SelectedOrder.GetChecksDiscounts(SHIFT.SelectedOrder,
                    _selectedSeatIndex, SHIFT.GlobalContext);
            if (_selectedDiscountIndex > 0)
            {
                _selectedDiscountIndex--;
            }
            else ///Wrap back around again.
            {
                _selectedDiscountIndex = discounts.Count() - 1;
            }
            SetCurrentDiscountAtDiscountWindow(discounts);
        }

        private static void SetCurrentDiscountAtDiscountWindow(List<ORDER.DiscountDisplay> discounts)
        {
            if (discounts.Count() == 0)
            {
                CloseCheckWindow.LabelDiscountNo.Content = "Discounts";
                CloseCheckWindow.LabelDiscountType.Content = "";
                CloseCheckWindow.LabelDiscountAppliedTo.Content = "";
                CloseCheckWindow.LabelDiscountManager.Content = "";
                CloseCheckWindow.LabelDiscountAmount.Content = "";
                CloseCheckWindow.RemoveDiscountButton.Visibility = Visibility.Hidden;
            }
            else
            {
                ORDER.DiscountDisplay discount = discounts[_selectedDiscountIndex];
                CloseCheckWindow.LabelDiscountNo.Content = "Discount " + (_selectedDiscountIndex + 1) + " of " + discounts.Count();
                CloseCheckWindow.LabelDiscountType.Content = discount.Type;
                CloseCheckWindow.LabelDiscountAppliedTo.Content = discount.AppliedTo;
                CloseCheckWindow.LabelDiscountManager.Content = discount.Manager;
                CloseCheckWindow.LabelDiscountAmount.Content = discount.Amount.ToString("c");
                CloseCheckWindow.RemoveDiscountButton.Visibility = Visibility.Visible;
            }
        }

        public static void RefreshDiscountWindow(bool advanceIdx = false)
        {
            List<ORDER.DiscountDisplay> discounts = SHIFT.SelectedOrder.GetChecksDiscounts(SHIFT.SelectedOrder,
                    _selectedSeatIndex, SHIFT.GlobalContext);
            if (advanceIdx)
            {
                _selectedDiscountIndex = discounts.Count() - 1;
            }
            if (discounts.Count() == 0)
            {
                CloseCheckWindow.LabelDiscountNo.Content = "Discounts";
                CloseCheckWindow.LabelDiscountType.Content = "";
                CloseCheckWindow.LabelDiscountAppliedTo.Content = "";
                CloseCheckWindow.LabelDiscountManager.Content = "";
                CloseCheckWindow.LabelDiscountAmount.Content = "";
                CloseCheckWindow.RemoveDiscountButton.Visibility = Visibility.Hidden;
            }
            else
            {
                ORDER.DiscountDisplay discount = discounts[_selectedDiscountIndex];
                CloseCheckWindow.LabelDiscountNo.Content = "Discount " + (_selectedDiscountIndex + 1) + " of " + discounts.Count();
                CloseCheckWindow.LabelDiscountType.Content = discount.Type;
                CloseCheckWindow.LabelDiscountAppliedTo.Content = discount.AppliedTo;
                CloseCheckWindow.LabelDiscountManager.Content = discount.Manager;
                CloseCheckWindow.LabelDiscountAmount.Content = discount.Amount.ToString("c");

                if (SHIFT.SelectedOrder.IsClosed)
                {
                    CloseCheckWindow.RemoveDiscountButton.Visibility = Visibility.Hidden;
                }
                else
                {
                    CloseCheckWindow.RemoveDiscountButton.Visibility = Visibility.Visible;
                }
            }
        }

        /// <summary>
        /// This function is called when a seat scroll, addition or button click has
        /// caused an event.
        /// </summary>
        /// <param Name="newIndex"></param>
        public static void SeatChangeOccured(int newIndex)
        {
            ///Update the selected index and selected seat, but first assure it is in bounds.
            if (newIndex >= 0 && newIndex < SHIFT.SelectedOrder.CheckCount)
            {
                ///Reset the line items scroll index on the customer ticket since we are
                ///switching to a different seat.
                _custTicketScrollIndex = 0;

                ///Update the selected seat index.
                _selectedSeatIndex = newIndex;
                IEnumerable<SALE> sales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
                _selectedSale = sales.FirstOrDefault();
                UpdateTicketFocus();
                _selectedDiscountIndex = 0;
                RefreshDiscountWindow();

                int paymentCount = SHIFT.SelectedOrder.GetChecksTransactions(CCBindings.SelectedSeatIndex).Count();
                if (CCBindings.SelectedTransactionIndex < (paymentCount - 1))
                {
                    CCBindings.SelectedTransactionIndex++;
                }
                else ///Wrap back to zero if we go over.
                {
                    CCBindings.SelectedTransactionIndex = 0;
                }
                RefreshThreadSafe();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void SetSeatTags()
        {
            int i = SHIFT.SelectedOrder.CheckCount - _selectedSeatIndex;
            int numBlanks = Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA - i;

            int seatNumber = (_selectedSeatIndex + 1);
            if (SHIFT.SelectedOrder.CheckCount <= Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
            {
                seatNumber = 1;
            }
            else if (numBlanks > 0)
            {
                seatNumber = seatNumber - numBlanks;
            }

            foreach (FlatButton_52_58 s in _seatButtonsList)
            {
                if (seatNumber > SHIFT.SelectedOrder.CheckCount)
                {
                    s.LabelNumber = 0;
                    s.LabelString = null;
                }
                else
                {
                    s.LabelNumber = seatNumber;
                    s.LabelString = "Check\n" + seatNumber;
                    seatNumber += 1;
                }
            }
        }


        /// <summary>
        /// Will scroll the seats to the right if possible
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatRight_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            try
            {
                e.Handled = true;
                int checkCount = SHIFT.SelectedOrder.CheckCount;
                if (_selectedSeatIndex != (checkCount - 1))
                {
                    if ((checkCount - _seatPivotIndex) > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                    {
                        _seatPivotIndex += 1;
                    }
                    SeatChangeOccured(_selectedSeatIndex + 1);
                    SetSeatTags();
                    SetScrollableSeatButtonsDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_RIGHT, exc);
            }
        }

        /// <summary>
        /// Scroll the seats to the left if possible.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatLeft_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                if (_selectedSeatIndex != 0)
                {
                    if ((_selectedSeatIndex - _seatPivotIndex) == 0)
                    {
                        _seatPivotIndex--;
                    }
                    SeatChangeOccured(_selectedSeatIndex - 1);
                    SetSeatTags();
                    SetScrollableSeatButtonsDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_LEFT, exc);
            }
        }
        /// <summary>
        /// Every window that inherits from PosWindow has the ability to override the following function
        /// to handle tasks that need to be taken care of before switching to this window.
        /// </summary>
        public static void PrepareForScreenChange_NOTHROW()
        {
            try
            {
                _prepaidMessageBox = null;
                _seatPivotIndex = 0;
                SeatChangeOccured(0);
                SetSeatTags();
                SetScrollableSeatButtonsDataContext();
                _selectedDiscountIndex = 0;
                CloseCheckWindow.CloseCheckBorder.DataContext = SHIFT.SelectedOrder;
                CloseCheckWindow.TableNumberLabel.Content = SHIFT.SelectedOrder.TableString;
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_PREPARE_FOR_SCREEN_CHANGE, exc);
            }
        }

        /// <summary>
        /// Scrolls the customers ticket up and down.
        /// </summary>
        /// <param Name="directionUp"></param>
        public static void TicketScrollClicked(bool directionUp)
        {
            if (directionUp)
            {
                _custTicketScrollIndex -= Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Since we just went ahead and knocked off an entire view panels worth, we
                ///need to assure we didn't drive negative.
                if (_custTicketScrollIndex < 0)
                {
                    _custTicketScrollIndex = 0;
                }
            }
            else  ///Must be scroll down
            {
                _custTicketScrollIndex += Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Make sure we didn't go too far, correct if we did by placing the view 
                ///at the end.
                IEnumerable<SALE> seatsSales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
                if (_custTicketScrollIndex >= seatsSales.Count())
                {
                    _custTicketScrollIndex = seatsSales.Count() - 1;
                }
            }
            UpdateTicketFocus();
        }

        /// <summary>
        /// Called before we leave this window.
        /// </summary>
        public static void PrepareForScreenLeave_NOTHROW()
        {
            CloseCheck.StateObject.CurrentViewedOrderCounter = 0;
            CloseCheckWindow.StopChangeDueBlink();
            CFD.WriteCustomStrings();
        }

        /// <summary>
        /// 
        /// </summary>
        public static void RefreshThreadSafe(bool setToLastIndex = false)
        {
            try
            {
                if (PosWindow.MainPosWindow.Dispatcher.CheckAccess())
                {
                    try
                    {
                        ///For debugging Quick Service Bug TODO Remove Eventually
                        if (SHIFT.SelectedOrder == null)
                        {
                            Logging.LogMessage("SHIFT.SelectedOrder == null in RefreshThreadSafe.");
                        }
                        List<TRANSACTION> tActions = SHIFT.SelectedOrder.GetChecksTransactions(SelectedSeatIndex).ToList();

                        ///Must pull this number to make sure it refreshes.
                        CloseCheckWindow.PaymentsGrid.DataContext = null;

                        if (tActions != null && tActions.Count != 0)
                        {
                            if (setToLastIndex)
                            {
                                _selectedTransactionIndex = tActions.Count - 1;
                            }

                            CloseCheckWindow.LabelPaymentNumber.Content = "Payment " + (_selectedTransactionIndex + 1) + " of " + tActions.Count;
                            CloseCheckWindow.PaymentsGrid.DataContext = tActions[_selectedTransactionIndex];
                        }
                        else
                        {
                            ///For debugging Quick Service Bug TODO Remove Eventually
                            if (tActions == null)
                            {
                                Logging.LogMessage("Transactions in RefreshThreadSafe was null.");
                            }
                            CloseCheckWindow.LabelPaymentNumber.Content = "Payments";
                            CloseCheckWindow.PaymentsGrid.DataContext = null;
                        }
                        CloseCheckWindow.GridChecksTotals.DataContext = null;
                        CloseCheckWindow.GridChecksTotals.DataContext = SHIFT.SelectedOrder;
                        CloseCheckWindow.LabelCheckNo.Content = "Check " + (_selectedSeatIndex + 1);

                        CloseCheck.StateObject.Refresh();
                        PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.CC);
                        SHIFT.SelectedOrder.OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(""));

                        ///Write the balance due to the display.
                        if (Constants.HasCfd)
                        {
                            decimal amountDue = SHIFT.SelectedOrder.CheckUnpaidGrandTotal(_selectedSeatIndex);
                            if (amountDue <= ORDER.ROUND_ERROR)
                            {
                                decimal change = CCBindings.SelectedTransaction.Change;
                                System.Threading.Tasks.Task.Factory.StartNew(() => CFD.WriteAmount(change, true));
                            }
                            else
                            {
                                System.Threading.Tasks.Task.Factory.StartNew(() => CFD.WriteAmount(amountDue, false));
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.LogException(e);
                    }
                }
                else
                {
                    PosWindow.MainPosWindow.Dispatcher.Invoke(new Action(() => RefreshThreadSafe(setToLastIndex)));
                }
            }
            catch (Exception e)
            {
                Logging.LogException(e);
            }
        }

        /// <summary>
        /// When the user touches the screen of the list view and the index of that list changes, this 
        /// event handler will fire.  It may also fire if the scroll arrows are using to scroll through
        /// the list.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void listViewCustTicket_SelectionChanged_NOTHROW(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                ListView callingLv = (sender as ListView);
                if (callingLv.IsMouseCaptureWithin)
                {
                    int idx = callingLv.SelectedIndex;

                    ///Make sure this does not return a negative numTimes.  When we are in the middle
                    ///of processing an event after a delete, this selected index change event will
                    ///fire even though we have not updated the selected index yet.
                    if (idx >= 0)
                    {
                        _custTicketScrollIndex = idx;
                        if (idx < Oceanside.OrderApi.CustomerTicketListView.Items.Count && idx > 0)
                        {
                            _selectedSale = Oceanside.OrderApi.CustomerTicketListView.Items[idx] as SALE;
                            if (!_selectedSale.IsForcedModifier && !_selectedSale.IsForcedModifier)
                            {
                                var q = from p in SHIFT.GlobalContext.PRODUCTS where p.Id == _selectedSale.ProductId select p;
                                if (q.Any())
                                {
                                    _selectedProduct = q.First();
                                }
                                else
                                {
                                    _selectedProduct = null;
                                }
                            }
                            else
                            {
                                _selectedProduct = null;
                            }
                        }
                    }
                    CloseCheck.StateObject.Refresh();
                    PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.CC);
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_CUST_TICKET_SELECTION_CHANGED, exc);
            }
        }

        /// <summary>
        /// Handles when a seat itself has been clicked rather than a scroller.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSeat_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                Oceanside.FlatButton_52_58 b = (Oceanside.FlatButton_52_58)e.Source;

                if (null != b)
                {
                    int zeroBasedIndx = ((int)b.LabelNumber) - 1;
                    if (zeroBasedIndx < SHIFT.SelectedOrder.CheckCount && zeroBasedIndx >= 0)
                    {
                        SeatChangeOccured(zeroBasedIndx);
                        RefreshThreadSafe();
                        foreach (FlatButton_52_58 seat in _seatButtonsList)
                        {
                            seat.Unselect();
                        }
                        b.Select();
                        SetScrollableSeatButtonsDataContext(false);
                    }
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_CCBIND_BUTTON_CHECK_CLICK, exc);
            }
        }

        /// <summary>
        /// This function assures that the scrollable seats display correctly.
        /// </summary>
        public static void SetScrollableSeatButtonsDataContext(bool updateSelction = true)
        {
            CloseCheckWindow.CustomerTicketListView.DataContext = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);

            if (updateSelction)
            {
                for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
                {
                    if (indx == (_selectedSeatIndex - _seatPivotIndex))
                    {
                        _seatButtonsList[indx].Select();
                    }
                    else
                    {
                        _seatButtonsList[indx].Unselect();
                    }
                }
            }
        }

        /// <summary>
        /// Should be called whenever we delete an item from the customer ticket or
        /// add or scroll items.
        /// </summary>
        public static void UpdateTicketFocus(bool focusLastItem = false)
        {
            List<SALE> sales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex).ToList();
            CloseCheckWindow.CustomerTicketListView.DataContext = sales;
            CloseCheckWindow.CustomerTicketListView.Items.Refresh();

            if (_custTicketScrollIndex >= sales.Count || focusLastItem)
            {
                _custTicketScrollIndex = sales.Count - 1;
                if (_custTicketScrollIndex < 0)
                {
                    _custTicketScrollIndex = 0;
                }
            }

            if (sales.Count != 0)
            {
                SALE selSale = sales[_custTicketScrollIndex];
                CloseCheckWindow.CustomerTicketListView.SelectedItem = selSale;
                CloseCheckWindow.CustomerTicketListView.UpdateLayout();
                CloseCheckWindow.CustomerTicketListView.ScrollIntoView(selSale);
            }
        }
    }
}
